﻿using System;
using System.Linq.Expressions;
using System.Reflection;

using BrightSword.Feber.Core;

namespace BrightSword.Feber.Samples
{
    /// <summary>
    ///     This is a sample of how to use the Feber library to create a composite function taking two arguments, computing a single aggregate value
    /// </summary>
    public static class FastComparer
    {
        /// <summary>
        ///     A generic method to compare two objects of type <typeparamref name="T" /> and return true if the property values on each scalar property are the same
        /// </summary>
        /// <param name="_this"></param>
        /// <param name="other"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static bool AllPropertiesAreEqualWith<T>(this T _this,
                                                        T other)
        {
            return FastComparer<T>.AllPropertiesAreEqual(_this,
                                                         other);
        }
    }

    public static class FastComparer<T>
    {
        private static readonly FastComparerBuilder _builder = new FastComparerBuilder();

        public static bool AllPropertiesAreEqual(T left,
                                                 T right)
        {
            return _builder.Function(left,
                                     right);
        }

        private class FastComparerBuilder : FunctionBuilder<T, T, T, bool>
        {
            protected override bool Seed
            {
                get { return true; }
            }

            protected override Func<Expression, Expression, Expression> Conjunction
            {
                get { return Expression.AndAlso; }
            }

            protected override Expression PropertyExpression(PropertyInfo property,
                                                             ParameterExpression leftInstanceParameterExpression,
                                                             ParameterExpression rightInstanceParameterExpression)
            {
                return Expression.Equal(Expression.Property(leftInstanceParameterExpression,
                                                            property),
                                        Expression.Property(rightInstanceParameterExpression,
                                                            property));
            }
        }
    }
}